#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "messagebox.h"
#include <QDateTime>
#include <QFileInfo>
#include <QFile>
#include <QTextStream>

#ifdef WIN32
    #include <winsock2.h>
    #include <windows.h>
    #include <winbase.h>
    #include <winnt.h>
#else
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
#endif

#include <string.h>
#include <stdio.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    Online = false;
    readSettings();

    setdial = new SettingsDialog(this);
    messwin = new MessagesWindow(this);

    ui->tableWidget->setRowCount(settings.dirName->length());
    ui->tableWidget->setVerticalHeaderLabels(*settings.dirName);

    traymenu = new QMenu(this);
    traymenu->addAction(ui->actionShow);
    traymenu->addAction(ui->actionConnect);
    traymenu->addAction(ui->actionDisconnect);
    traymenu->addAction(ui->actionAbout);
    traymenu->addAction(ui->actionAbout_QT);
    traymenu->addAction(ui->actionExit);

    trayicon = new QSystemTrayIcon(QIcon(":/res/images/offline32.png"), this);
    trayicon->setToolTip("QInetAccess");
    trayicon->setContextMenu(traymenu);
    trayicon->show();

    timer = new QTimer(this);
    timer->setInterval(5000);
    timer->setSingleShot(false);

    timer2 = new QTimer(this);
    timer2->setInterval(200);
    timer2->setSingleShot(true);

    filemutex = new QMutex();

    codec = QTextCodec::codecForName("Windows-1251");

    connect(ui->pushButtonSettings, SIGNAL(clicked()), this, SLOT(showSettingsDialog()));
    connect(ui->pushButtonMessages, SIGNAL(clicked()), this, SLOT(showMessagesWindow()));
    connect(ui->pushButtonConnect, SIGNAL(toggled(bool)), this, SLOT(connectPressed(bool)));
    connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(closeApplication()));
    connect(ui->actionShow, SIGNAL(triggered()), this, SLOT(show()));
    connect(trayicon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconClicked(QSystemTrayIcon::ActivationReason)));
    connect(ui->actionAbout, SIGNAL(triggered()), this, SLOT(aboutProgram()));
    connect(ui->actionConnect, SIGNAL(triggered()), this, SLOT(connectToServer()));
    connect(ui->actionDisconnect, SIGNAL(triggered()), this, SLOT(disconnectFromServer()));
    connect(timer, SIGNAL(timeout()), this, SLOT(timerTimeout()));
    connect(timer2, SIGNAL(timeout()), this, SLOT(timerTimeout()));
    connect(ui->actionAbout_QT, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

MainWindow::~MainWindow()
{
    delete ui;
    delete setdial;
    delete messwin;
    delete trayicon;
    delete traymenu;
    delete timer;
    delete timer2;
    delete filemutex;
}

//public: ///////////////////////////////////////////////////////////
void MainWindow::On()
{
    if (!Online)
    {
        trayicon->setIcon(QIcon(":/res/images/online32.png"));
        ui->labelConnected->setText(tr("Connected"));
        QColor green(Qt::green);
        QPalette palette = ui->labelConnected->palette();
        palette.setColor(QPalette::WindowText, green);
        ui->labelConnected->setPalette(palette);
        Online = true;
    }
}

void MainWindow::Off()
{
    if (Online)
    {
        trayicon->setIcon(QIcon(":/res/images/offline32.png"));
        ui->labelConnected->setText(tr("Disconnected"));
        QColor red(Qt::red);
        QPalette palette = ui->labelConnected->palette();
        palette.setColor(QPalette::WindowText, red);
        ui->labelConnected->setPalette(palette);
        Online = false;
    }
}

void MainWindow::setClientProt(CLIENTPROT *cp)
{
    clnp = cp;
}

void MainWindow::setDirNames(const QStringList &dirs)
{
    settings.dirName = new QStringList(dirs);
    ui->tableWidget->setRowCount(dirs.length());
    ui->tableWidget->setVerticalHeaderLabels(dirs);
}

//private: //////////////////////////////////////////////////////////////////////////////////////
void MainWindow::closeEvent(QCloseEvent *event)
{
    if (settings.minimizeOnClose)
    {
        event->ignore();
        hide();
    }
    else
    {
        if (okToExit())
        {
            trayicon->hide();
            writeSettings();
            setdial->close();
            messwin->close();
            qApp->quit();
        }
        else
        {
            event->ignore();
        }
    }
}

void MainWindow::writeSettings()
 {
     QSettings sets(QSettings::IniFormat, QSettings::UserScope, "stg", "qinetaccess", this);

     sets.beginGroup("MainWindow");
     sets.setValue("size", size());
     sets.setValue("pos", pos());
     sets.setValue("login", ui->lineEditLogin->text());
     if (settings.savePass)
     {
         sets.setValue("password", ui->lineEditPassword->text());
     } else
     {
         sets.setValue("password", QString());
     }
     sets.endGroup();

     sets.beginGroup("Settings");
     sets.setValue("ip", settings.serverIP);
     sets.setValue("port", settings.serverPort);
     sets.setValue("dirs", *settings.dirName);
     sets.setValue("autoconnect", settings.autoconn);
     sets.setValue("reconnect", settings.reconnect);
     sets.setValue("savepassword", settings.savePass);
     sets.setValue("minimizeonclose", settings.minimizeOnClose);
     sets.setValue("hintmoney", settings.outHintCash);
     sets.setValue("hinttraffic", settings.outHintTraffic);
     sets.setValue("hintdir", settings.outHintTrafficDir);
     sets.setValue("stattype", settings.statType);
     sets.setValue("showsumm", settings.showSumm);
     sets.endGroup();
 }

 void MainWindow::readSettings()
{
     QSettings sets(QSettings::IniFormat, QSettings::UserScope, "stg", "qinetaccess", this);

     sets.beginGroup("MainWindow");
     resize(sets.value("size", QSize(438, 245)).toSize());
     move(sets.value("pos", QPoint(200, 200)).toPoint());
     ui->lineEditLogin->setText(sets.value("login", "").toString());
     ui->lineEditPassword->setText(sets.value("password", "").toString());
     sets.endGroup();

     sets.beginGroup("Settings");
     settings.serverIP = sets.value("ip", "").toString();
     settings.serverPort = sets.value("port", 5555).toInt();
     settings.dirName = new QStringList(sets.value("dirs", "Internet").toStringList());
     settings.autoconn = sets.value("autoconnect", 0).toInt();
     settings.reconnect = sets.value("reconnect", 0).toInt();
     settings.savePass = sets.value("savepassword", 0).toInt();
     settings.minimizeOnClose = sets.value("minimizeonclose", 0).toInt();
     settings.outHintCash = sets.value("hintmoney", 0).toInt();
     settings.outHintTraffic = sets.value("hinttraffic", 0).toInt();
     settings.outHintTrafficDir = sets.value("hintdir", 0).toInt();
     settings.statType = sets.value("stattype", ST_F).toInt();
     settings.showSumm = sets.value("showsumm", 0).toInt();
     settings.messagesfile = QFileInfo(sets.fileName()).absolutePath() + "/messages.db";
     sets.endGroup();
}

bool MainWindow::okToExit()
{
    raise();
    activateWindow();
    return (QMessageBox::question(this, tr("Warning"),
            tr("Do you want to close application"),
            QMessageBox::Yes | QMessageBox::No)==QMessageBox::Yes);
}

//public slots:   !!!!!!!!!!!!!!!!!!!!!!Слоты!!!!!!!!!!!!!!!!!!!
void MainWindow::showSettingsDialog()
{
    setdial->putSettings(settings);
    setdial->ServerChanged = false;
    if (setdial->exec()==QDialog::Accepted)
    {
        setdial->storeSettings(settings);
        if (setdial->ServerChanged)
        {
            QMessageBox::information(this, tr("Information"), tr("Please, restart qinetaccess to apply settings"), QMessageBox::Ok);
        }
    }
}

void MainWindow::showMessagesWindow()
{
    messwin->setMessageFilePath(settings.messagesfile);
    messwin->updateMessageCount("10");
    messwin->show();
}

void MainWindow::connectPressed(bool is)
{
    if (is)
    {
        connectToServer();
    }
    else
    {
        disconnectFromServer();
    }
}

void MainWindow::closeApplication()
{
    if (okToExit())
    {
        trayicon->hide();
        writeSettings();
        setdial->close();
        messwin->close();
        qApp->quit();
    }

}

void MainWindow::iconClicked(QSystemTrayIcon::ActivationReason reason)
{
    if (reason==QSystemTrayIcon::DoubleClick)
    {
        if (isHidden())
        {
            show();
            raise();
            activateWindow();
        }
        else
        {
            hide();
        }
        return;
    }

    else if (reason==QSystemTrayIcon::Trigger)
    {
        raise();
        activateWindow();
    }

}

void MainWindow::aboutProgram()
{
    QMessageBox::information(this, tr("About"), tr("QInetAccess v.0.1.1\nStiff <stiff11@ya.ru>"), QMessageBox::Ok);
}


void MainWindow::updateStatistics()
{
    LOADSTAT stat;
    clnp->GetStat(stat);

    QString cstr, traffichintstr;
    cstr.sprintf("%.2f", stat.cash / 1000.0);
    ui->labelMoney->setText(cstr);
    trayicon->setToolTip("QInetAccess");
    if (settings.outHintCash)
    {
        trayicon->setToolTip(trayicon->toolTip()+"\n"+tr("Cash balance: ")+cstr);
    }

    if ((stat.freeMb[0]=='C') || (stat.freeMb[0]=='c'))
    {
        ui->labelTraffic->setText(QString(stat.freeMb+1));
    }

    if (!settings.showSumm)
    {
        for (int i=0; i<settings.dirName->length(); i++)
        {
            QString sess(IntToKMG(stat.sd[i], settings.statType));
            sess=sess+ " / "+ QString(IntToKMG(stat.su[i], settings.statType));
            ui->tableWidget->setItem(i, 0, new QTableWidgetItem(sess));

            QString month(IntToKMG(stat.md[i], settings.statType));
            month=month+ " / "+ QString(IntToKMG(stat.mu[i], settings.statType));
            ui->tableWidget->setItem(i, 1, new QTableWidgetItem(month));
            if ((settings.outHintTraffic) && (i==settings.outHintTrafficDir))
            {
                trayicon->setToolTip(trayicon->toolTip()+"\n"+tr("Traffic for session: ")+sess+tr("; for month: ")+month);
            }
        }
    } else
    {
        for (int i=0; i<settings.dirName->length(); i++)
        {
            QString sess(IntToKMG(stat.sd[i]+stat.su[i], settings.statType));
            ui->tableWidget->setItem(i, 0, new QTableWidgetItem(sess));

            QString month(IntToKMG(stat.md[i]+stat.mu[i], settings.statType));
            ui->tableWidget->setItem(i, 1, new QTableWidgetItem(month));
            if ((settings.outHintTraffic) && (i==settings.outHintTrafficDir))
            {
                trayicon->setToolTip(trayicon->toolTip()+"\n"+tr("Traffic for session: ")+sess+tr("; for month: ")+month);
            }
        }
    }
}

void MainWindow::connectToServer()
{
    if (ui->lineEditLogin->text().isEmpty())
    {
        QMessageBox::warning(this, tr("Error"), tr("Please, type login"));
        ui->pushButtonConnect->setChecked(false);
        ui->lineEditLogin->setFocus();
        return;
    }
    if (ui->lineEditPassword->text().isEmpty())
    {
        QMessageBox::warning(this, tr("Error"), tr("Please, type password"));
        ui->pushButtonConnect->setChecked(false);
        ui->lineEditPassword->setFocus();
        return;
    }
    ui->lineEditLogin->setReadOnly(true);
    ui->lineEditPassword->setReadOnly(true);
    ui->pushButtonConnect->setText(tr("Disconnect"));
    if (! ui->pushButtonConnect->isChecked())
    {
        ui->pushButtonConnect->setChecked(true);
    }
    clnp->SetReconnect(settings.reconnect);
    clnp->SetLogin(ui->lineEditLogin->text().toAscii().data());
    clnp->SetPassword(ui->lineEditPassword->text().toAscii().data());
    clnp->Connect();
    timer->start();
    timer2->start();
}

void MainWindow::disconnectFromServer()
{
    timer->stop();
    clnp->Disconnect();
    ui->pushButtonConnect->setText(tr("Connect"));
    ui->lineEditLogin->setReadOnly(false);
    ui->lineEditPassword->setReadOnly(false);
    if (ui->pushButtonConnect->isChecked())
    {
        ui->pushButtonConnect->setChecked(false);
    }
}

//Слоты, соединяемые с протоколом
void MainWindow::Foo(int a)
{
    if (a)
        this->On();
    else
    {
        this->Off();
    }
}

void MainWindow::ShowMessage(const char * message, int i, int showTime, int sendTime)
{
    QString qmsg = codec->toUnicode(message);
    messagebox *mb = new messagebox();
    mb->showMessageBox(qmsg, showTime, sendTime);
    QString str = "<b>" + tr("Sent: ") + QDateTime::fromTime_t(sendTime).toString("dd.MM.yyyy hh:mm:ss")
                  + tr("    Received: ") + QDateTime::currentDateTime().toString("dd.MM.yyyy HH:mm:ss") + "</b><br>"
                  + qmsg + "<br>\n";
    filemutex->lock();
    QFile messdb(settings.messagesfile);
    if (messdb.open(QIODevice::WriteOnly | QIODevice::Append))
    {
        QTextStream stream(&messdb);
        stream << str;
        messdb.close();
    }
    filemutex->unlock();
}

void MainWindow::SetDirName(const string16 * dn, int winKOI)
{
    int i = 0;
    QStringList sl;
    while (dn[i][0]!=0)
    {
        if (dn[i][0]!=0)
        {
            QString str(dn[i]);
            sl << str;
        }
        i++;
    }
    this->setDirNames(sl);
}

void MainWindow::timerTimeout()
{
    int err = clnp->GetErrMes();
    switch (err)
    {
        case 1:
            QMessageBox::warning(this, tr("Warning"), tr("Bind failed. Does another copy of qinetaccess running?"), QMessageBox::Ok);
            trayicon->hide();
            qApp->exit(0);
            break;
        case 2:
            char s1[255];
            clnp->GetMessageText(s1, 255);
            QString msgtext = codec->toUnicode(s1);
            QMessageBox::warning(this, tr("Server reports about eror:"), msgtext, QMessageBox::Ok);
            break;
    }
    updateStatistics();
}
